package com.hd.trans.utils.preference

import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.hd.trans.extension.fromJson
import com.hd.trans.extension.gson
import com.hd.trans.ui.base.AppContextProvider
import kotlin.reflect.KProperty


/**
 * @author       qianjujun
 * @email        qianjujun@163.com
 * @createTime  2020/12/31 14:07
 * @describe
 */
class Preference<T : Any>(var name:String,  val default:T) {

    fun updateName(name:String){
        this.name = name
    }

    val prefs: SharedPreferences by lazy {
        AppContextProvider.getContext().getSharedPreferences("transSdk", Context.MODE_PRIVATE)
    }

    inline operator fun <reified T:Any> getValue(thisRef: Any?, property: KProperty<*>): T {
        return when (default) {
            is Long -> prefs.getLong(name, default) as T
            is String -> prefs.getString(name, default) as T
            is Int -> prefs.getInt(name, default) as T
            is Boolean -> prefs.getBoolean(name, default) as T
            is Float -> prefs.getFloat(name, default) as T
            else -> {
                if (!prefs.contains(name)) {
                    default as T
                } else {
                    val json = prefs.getString(name, gson.toJson(default))
                    gson.fromJson(json!!) as T
                }
            }
        }
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putSharedPreferences(name, value)
    }

    @SuppressLint("CommitPrefEdits")
    private fun putSharedPreferences(name: String, value: T) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value).commit()
            is String -> putString(name, value).commit()
            is Int -> putInt(name, value).commit()
            is Boolean -> putBoolean(name, value).commit()
            is Float -> putFloat(name, value).commit()
            else -> putString(name, jsonToString(value)).commit()
        }
    }

    @Suppress("UNCHECKED_CAST")
    private inline fun <reified T : Any> getSharedPreferences(name: String, default: T): T = with(prefs) {
        val res: Any? = when (default) {
            is Long -> getLong(name, default)
            is String -> getString(name, default)
            is Int -> getInt(name, default)
            is Boolean -> getBoolean(name, default)
            is Float -> getFloat(name, default)
            else ->  gson.fromJson(getString(name, jsonToString(default))!!)
        }

        return res as T
    }

    /**
     * 删除全部数据
     */
    fun clearPreference() {
        prefs.edit().clear().apply()
    }

    /**
     * 根据key删除存储数据
     */
    fun clearPreference(key: String) {
        prefs.edit().remove(key).apply()
    }


     fun <A> jsonToString(obj: A): String {
        return gson.toJson(obj)
    }


     inline fun <reified T : Any> parseJson(str: String): T {
        return gson.fromJson(str)
    }


    /**
     * 查询某个key是否已经存在
     *
     * @param key
     * @return
     */
    fun contains(key: String): Boolean {
        return prefs.contains(key)
    }

    /**
     * 返回所有的键值对
     *
     * @param context
     * @return
     */
    fun getAll(): Map<String, *> {
        return prefs.all
    }
}